package com.qg.base.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author QG
 * @version 1.0
 * @date 2023/7/18 15:19
 */
public class ReflectUtil {

    public static <T> T copySameFields(Object source, T target) {
        Class<?> sourceClass = source.getClass();
        Field[] declaredFields = sourceClass.getDeclaredFields();
        Class<?> targetClass = target.getClass();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            Object value = null;
            try {
                // 获取源值
                value = declaredField.get(source);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (Objects.isNull(value)) {
                continue;
            }

            Method[] methods = targetClass.getMethods();
            for (Method method : methods) {
                method.setAccessible(true);
                String name = method.getName();
                // 获取target的set方法，限制set方法的参数个数只有一个,类型也相同
                if (name.equals(buildSetMethod(declaredField.getName()))
                        && method.getParameters().length == 1
                        && method.getParameters()[0].getType().equals(declaredField.getType())) {
                    try {
                        method.invoke(target, value);
                        break;
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return target;
    }

    private static String buildSetMethod(String fieldName) {
        return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }

    private static String buildGetMethod(String fieldName) {
        return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }


    public static Object getGetMethodValue(Object object, Field filed) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String getMethodName = buildGetMethod(filed.getName());
        filed.setAccessible(true);
        Method declaredMethod;
        declaredMethod = object.getClass().getDeclaredMethod(getMethodName);
        return declaredMethod.invoke(object);

    }


    public static void setMethodValue(Object object, Field filed, Object... value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String getMethodName = buildSetMethod(filed.getName());
        filed.setAccessible(true);
        Method declaredMethod;
        declaredMethod = object.getClass().getDeclaredMethod(getMethodName, filed.getType());
        declaredMethod.invoke(object, value);

    }

}
